﻿namespace Raven
{
    public class GoalSeekToPosition : Goal<RavenBot>
    {
        private Vector2 _position;

        //the approximate time the bot should take to travel the target location
        private Fix _timeToReachPos;

        //this records the time this goal was activated
        private Fix _startTime;

        //returns true if a bot gets stuck
        private bool isStuck()
        {
            Fix TimeTaken = _owner.GetWorld().GetTimer().currentTime - _startTime;

            if (TimeTaken > _timeToReachPos)
            {
                Logger.Log("BOT " + _owner.ID() + " IS STUCK!!");

                return true;
            }

            return false;
        }

        public GoalSeekToPosition(RavenBot owner, Vector2 target) : base(owner, GoalType.goal_seek_to_position)
        {
            _position = target;
            _timeToReachPos = 0;
        }

        public override void Activate()
        {
            _status = GoalStatus.active;
  
            //record the time the bot starts this goal
            _startTime = _owner.GetWorld().GetTimer().currentTime;    
  
            //This value is used to determine if the bot becomes stuck 
            _timeToReachPos = _owner.CalculateTimeToReachPosition(_position);
  
            //factor in a margin of error for any reactive behavior
            Fix MarginOfError = 1;

            _timeToReachPos += MarginOfError;

  
            _owner.GetSteering().SetTarget(_position);

            _owner.GetSteering().SeekOn();
        }

        public override GoalStatus Process()
        {
            //if status is inactive, call Activate()
            ActivateIfInactive();
    
            //test to see if the bot has become stuck
            if (isStuck())
            {
                _status = GoalStatus.failed;
            }
  
            //test to see if the bot has reached the waypoint. If so terminate the goal
            else
            { 
                if (_owner.isAtPosition(_position))
                {
                    _status = GoalStatus.completed;
                }
            }

            return _status;
        }

        public override void Terminate()
        {
            _owner.GetSteering().SeekOff();
            _owner.GetSteering().ArriveOff();

            _status = GoalStatus.completed;
        }
    }
}